4

一,概述

  1. 为什么会出现跨域问题
    同源策略是浏览器安全的基石,首先由NetScape 公司引入浏览器,目前所有浏览器都实行这个政策。同源策略是一种约定,所谓同源策略,指的是浏览器对不同源的脚本或文本的访问进行限制,例如源A的js 不能读取和设置引入的源的元素属性。只有同协议 同域名 同端口 下才能访问。因为浏览器的同源策略的存在,才有了跨域问题。
  2. 同源策略的限制范围
(1)cookie,LocalStorage,和IndexDB 无法读取

(2)DOM 无法获得

(3)Ajax请求不能发送
  1. 没有同源策略限制的两大危险场景

    (1)没有同源策略限制的接口请求:
    cookie一般用来处理登录场景,目的是让服务器知道谁发的这次请求。如果你请求接口进行登录,服务端验证通过后会在响应头加入 Set-Cookie 字段,然后下次再发请求的时候,浏览器会自动将cookie 附加在HTTP请求的头字段Cookie中,服务端就知道这个用户已经登录过了。问题也就来了,如果你登录一个银行网站A,然后又进入一个非法网站B,如果没有同源策略,那么非法网站就会获取你登录A 网站的Cookie,这样一来不发网站就可以登录你A网站的账号为所欲为。这就是传说中的 CSRF攻击

    (2)没有同源策略限制的DOM查询:
    最常见的就是钓鱼网站。 有一天你收到一封邮件,说你的银行账户有风险,干净登录www.yinghang.com 进行修改,你打开界面发现和你以前登录的网站一模一样,然后你输入账户和密码登陆后发现账户余额正常,就离开了。可是你平时登录银行账户的网站是www.yinhang.com。这个钓鱼网站做了什么呢?

html
<iframe></iframe>

js    
var ifram = window.frames['yinhang'];
var account = iframe.document.getElementById("你输入账户的输入框")
var pwd     = iframe.document.getElementById("你输入账户的密码框")

如果没有同源策略限制,你的账户和密码就会被非网站获取

二,跨域的解决方案(AJAX)

同源策略规定,AJAX请求只能发给同源的网址,否则就会报错。除了架设服务器代理
(浏览器请求同源服务器,后者再请求外部服务),有三种方法可以解决
  • JSONP
  • Websocket
  • CORS
  1. JSONP

它的思想是,网页通过添加一个<script>元素,向服务器请求JSON数据,这种做法不受同源策略限制。服务器收到请求后,将数据放在一个指定名字的回调函数里传回来。
首先,网页动态插入<script>元素,由它向跨源网址发出请求。

function addScriptTag(src) {
  var script = document.createElement('script');
  script.setAttribute("type","text/javascript");
  script.src = src;
  document.body.appendChild(script);
}

window.onload = function () {
  addScriptTag('http://example.com/ip?callback=foo');
}

function foo(data) {
  console.log('Your public IP address is: ' + data.ip);
};

注意请求的查询字符串有一个callback参数,用来指定回调函数的名字,这是JSONP必须的,服务器收到请求后,会将数据放在回调函数的参数位置返回。

foo({
    "ip":"192.168.1.159"
})

由于<script>元素请求的脚本,直接作为代码运行。这时只要浏览器定义了foo函数,该函数会被立即调用。

2.WebSocket

WebSocket 是一种通信协议,使用 ws://(非加密) 和 wss://(加密)作为协议前缀。该协议不实行同源策略,只要服务器支持,就可以通过它进行通信。

var ws = new WebSocket('wss://echo.websocket.org');

      ws.onopen = function (evt) {
          console.log('Connection open ...');
          ws.send('Hello WebSockets!');
      };

      ws.onmessage = function (evt) {
          console.log('Received Message: ', evt.data);
          ws.close();
      };

      ws.onclose = function (evt) {
          console.log('Connection closed.');
      };
3.CORS

CORS 是跨源资源分享(Cross-Origin Resource sharing) 的缩写,它是W3c标准,是跨域AJAX请求的根本解决办法。相比JSONP只能发GET请求,CORS允许任何类型的请求。
CORS需要浏览器和服务器同时支持。目前,所有浏览器都支持该功能,IE浏览器不能低于IE10。

整个CORS通信过程,都是浏览器自动完成,不需要用户参与。对于开发者来说,CORS通信与同源的AJAX通信没有差别,代码完全一样。浏览器一旦发现AJAX请求跨源,就会自动添加一些附加的头信息,有时还会多出一次附加的请求,但用户不会有感觉。

因此,实现CORS通信的关键是服务器(服务器端可是判断,让那些域可以请求)。只要服务器实现了CORS接口,
就可以跨源通信。


smallgang
232 声望7 粉丝